using System.ComponentModel.Design;
using System.Reflection;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VsSDK.UnitTestLibrary;
using ThreadSafe.JSense.VSIX;

namespace ThreadSafe.JSense.VSIX_UnitTests.MenuItemTests
{
   [TestClass]
   public class MenuItemTest
   {
      /// <summary>
      /// Verify that a new menu command object gets added to the OleMenuCommandService. 
      /// This action takes place In the Initialize method of the Package object
      /// </summary>
      [TestMethod]
      public void InitializeMenuCommand()
      {
         // Create the package
         IVsPackage package = new ThreadSafeJSenseVsixPackage();
         Assert.IsNotNull(package, "The object does not implement IVsPackage");

         // Create a basic service provider
         var serviceProvider = OleServiceProvider.CreateOleServiceProviderWithBasicServices();

         // Site the package
         Assert.AreEqual(0, package.SetSite(serviceProvider), "SetSite did not return S_OK");

         //Verify that the menu command can be found
         var menuCommandID = new CommandID(GuidList.GuidThreadSafeJSenseVsixCmdSet, (int) PkgCmdIDList.CmdIdJSense);
         var info = typeof (Package).GetMethod("GetService", BindingFlags.Instance | BindingFlags.NonPublic);
         Assert.IsNotNull(info);
         var mcs = info.Invoke(package, new object[] {(typeof (IMenuCommandService))}) as OleMenuCommandService;
         if (mcs != null) Assert.IsNotNull(mcs.FindCommand(menuCommandID));
      }

      [TestMethod]
      public void MenuItemCallback()
      {
         // Create the package
         IVsPackage package = new ThreadSafeJSenseVsixPackage();
         Assert.IsNotNull(package, "The object does not implement IVsPackage");

         // Create a basic service provider
         var serviceProvider = OleServiceProvider.CreateOleServiceProviderWithBasicServices();

         // Create a UIShell service mock and proffer the service so that it can called from the MenuItemCallback method
         var uishellMock = UIShellServiceMock.GetUiShellInstance();
         serviceProvider.AddService(typeof (SVsUIShell), uishellMock, true);

         // Site the package
         Assert.AreEqual(0, package.SetSite(serviceProvider), "SetSite did not return S_OK");

         //Invoke private method on package class and observe that the method does not throw
         var info = package.GetType().GetMethod("MenuItemCallback", BindingFlags.Instance | BindingFlags.NonPublic);
         Assert.IsNotNull(info, "Failed to get the private method MenuItemCallback throug refplection");
         info.Invoke(package, new object[] {null, null});

         //Clean up services
         serviceProvider.RemoveService(typeof (SVsUIShell));

      }
   }
}
